/*
Rilego - An easy Images 2 E-Book converter.
Copyright (C) 2011  Federico Improta (Kirys)

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 */
package it.kirys.rilego.engine.processors;

import it.kirys.rilego.engine.Engine;
import it.kirys.rilego.engine.loaders.imagesources.IImageSource;
import it.kirys.rilego.engine.outputbuilders.IMediaType;
import it.kirys.rilego.engine.processors.imagefilters.FiltersList;
import it.kirys.rilego.engine.processors.transformers.ITransformer;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;

/**
 *
 * @author Federico Improta
 */
public abstract class AbstractFullProcessor implements IImageProcessor {
	IMediaType mediaType;
	FiltersList filters;
	ProcessorOutput[] outputs;
	IImageSource source;
	ICompressor compressor;
	ITransformer transformer;
	Engine engine;

	public FiltersList getFilters() {
		return filters;
	}

	public ICompressor getCompressor() {
		return compressor;
	}

	public ITransformer getTransformer() {
		return transformer;
	}

	/**
	 * Process an image and return the result images
	 * @param source Image to process
	 * @return 1 or more images result of the process
	 */

	protected abstract BufferedImage[] process(BufferedImage source);

	/**
	 * Generate a single preview image
	 * @return a buffered image that can be used as a preview
	 * @throws IOException
	 */
	public BufferedImage preview() throws IOException{
			BufferedImage b=loadFromStream(getSourceImage().getStream());
			BufferedImage[] images =process(b);
			return images[0];
	}

	/**
	 * Simple method for loading an image from a stream
	 * @param stream source stream
	 * @return buffered image
	 * @throws IOException
	 */
	public static synchronized BufferedImage loadFromStream(InputStream stream) throws IOException {
		BufferedInputStream bstream = new BufferedInputStream(stream);
		return ImageIO.read(bstream);
	}//public static BufferedImage loadFromStream(InputStream stream) throws IOException

	@Override
	final public void run() {
		long processTime=java.lang.System.currentTimeMillis();

		/*
		 * We have to load the image and the give the control to the son
		 */
		try {
			BufferedImage b=loadFromStream(getSourceImage().getStream());
			BufferedImage[] images =process(b);
			LinkedList<ProcessorOutput> outlist= new LinkedList<ProcessorOutput>();
			if (images!=null){
				for (BufferedImage image:images){
					ProcessorOutput output= getCompressor().compress(image);
					outlist.add(output);					
				}
			}
			outputs = outlist.toArray(new ProcessorOutput[]{});
			processTime = java.lang.System.currentTimeMillis()-processTime;
			engine.logMessage(String.format("Source '%s' processed in %d s", getSourceImage().getIdentifier(),processTime/1000));
		} catch (Exception ex) {
			engine.logException(String.format("Error during source '%s' Processing", getSourceImage().getFullIdentifier()), ex);
		}//final public void run()

	}

	@Override
	public IImageSource getSourceImage() {
		return source;
	}

	@Override
	public ProcessorOutput[] getOutput() {
		return outputs;
	}

	public AbstractFullProcessor(FiltersList filters, ITransformer transformer,IMediaType mediaType, ICompressor compressor, IImageSource source, Engine engine) {
		outputs = null;
		if (filters != null) {
			this.filters = filters.clone();
		} else {
			this.filters = null;
		}
		this.mediaType=mediaType;
		this.engine = engine;
		this.compressor = compressor;
		this.source = source;
		this.transformer = transformer;
	}

	@Override
	public Engine getEngine() {
		return this.engine;
	}
}
